<?php

namespace App\Http\Controllers\v1;


use App\Libs\Conf;
use App\Models\Area;
use App\Models\Org;
use App\Models\Project;
use App\Models\SmsCode;
use App\Models\Team;
use App\Models\User;
use App\Models\UserCollection;
use App\Models\UserProject;
use App\Models\UserScore;
use App\Models\Volunteer;
use App\Models\VolunteerGoodAt;
use EasyWeChat\Core\Exception;
use Illuminate\Http\Request;
use App\Libs\IdCard;

use App\Http\Requests;
use App\Http\Controllers\Controller;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Input;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Validator;
use Hashids\Hashids;


class UserController extends Controller
{

    public function register(Request $request)
    {
        $rules = [  'phone'=>'required|is_phone', 'verify_code'=>'required', 'pwd'=>'required', 'avatars'=>'url'];
        $validator = Validator::make(Input::all(), $rules);
        if($validator->fails())
        {
            $errors = $validator->errors();
            $this->setStatus(10001);
            $this->setMsg(implode(' ', $errors->all()));

            return $this->response();
        }

        if(empty(request()->header('X-unique-key', '')))
        {
            $this->setStatus(10001);
            $this->setMsg('unique key为必填');

            return $this->response();
        }
        $username = $request->input('username', $request->input('phone'));
        if(!preg_match('/^[\x{4e00}-\x{9fa5}a-zA-Z0-9]+$/u', $username))
        {
            $this->setStatus(10001);
            $this->setMsg('用户名只能由中英文和数字组成');
            return $this->response();
        }

        if(!preg_match('/^[a-zA-Z0-9]+$/u', $request->input('pwd')) || strlen($request->input('pwd')) < 6 || strlen($request->input('pwd')) > 20)
        {
            $this->setStatus(10001);
            $this->setMsg('密码只能由数字或者字母组成,长度在6~20字符');
            return $this->response();
        }

        $phone = $request->input('phone');
        $verifyCode = $request->input('verify_code');
        //检查验证码
        $checkSms = SmsCode::checkVerifyCode($phone, $verifyCode);
        if( !$checkSms )
        {
            $this->setStatus(10001);
            $this->setMsg('短信验证码错误,请重新获取验证码!');
            return $this->response();
        }
        $username = $request->input('username',$request->input('phone'));

        $checkPhone = User::where('type', 1)->where(function($query) use ($username){
            $query->where('username', $username);
        })->where('org_id', $this->getOrdId())->first();

        if(!empty($checkPhone))
        {
            $this->setStatus(10001);
            $this->setMsg('您的用户名已经被其他账号使用!');
            return $this->response();
        }

        $checkPhone = User::where('type', 1)->where(function($query) use ( $phone){
            $query->where('phone', $phone);
        })->where('org_id', $this->getOrdId())->first();

        if(!empty($checkPhone))
        {
            $this->setStatus(10001);
            $this->setMsg('您的电话已经被其他账号使用!');
            return $this->response();
        }
        DB::beginTransaction();
        try{
            $userInfo = new User();
            $data = Input::all();
            $data['username'] = $username;
            $data['type'] = 1;
            $data['org_id'] = $this->getOrdId();
            $data['pwd'] = Hash::make($request->input('pwd'));
            $data['avatars'] = $request->input('avatars', '');
            $data['token'] = User::createToken();
            $data['open_id'] = request()->header('X-unique-key', '');
            $userInfo->fill($data)->save();

            $volunteer = new Volunteer();
            $volunteer->phone = $userInfo->phone;
            $volunteer->org_id = $userInfo->org_id;
            $volunteer->user_id = $userInfo->id;
            $volunteer->identifier = 'V'.date('ymd').sprintf('%06d', $userInfo->id);
            $volunteer->score = Org::getScoreConf()['register'];

            $orgId = $this->getOrdId();
            if($orgId == 38)
            {
                $volunteer->slogan = '志愿小金人，用爱传温暖！';
            }
            $volunteer->save();

            $format = $userInfo->getAllInfo();
            $format['token'] = $userInfo->token;

            DB::table('user_score_item')->insert(['user_id'=>$userInfo->id, 'type'=>0, 'score'=>Org::getScoreConf()['register'], 'remark'=>'注册奖励']);
            DB::commit();
            Log::info('SCORE 注册奖励积分 userId:'.$userInfo->id.'  score:'.Org::getScoreConf()['register']);
            $this->setData($format);
            return $this->response();

        }catch (\Exception $e)
        {
            Log::info($request->all());
            Log::info($e->getMessage());
            DB::rollBack();
            $this->setStatus(-10001);
            $this->setMsg('服务器忙,请稍后重试');
            return $this->response();
        }

    }

    public function _registerByPhone()
    {
        DB::beginTransaction();
        try{
            $userInfo = new User();
            $data = Input::all();
            $data['username'] = request()->input('phone');
            $data['type'] = 1;
            $data['org_id'] = $this->getOrdId();
            $data['pwd'] = '';
            $data['avatars'] = '';
            $data['token'] = User::createToken();
            $data['open_id'] = request()->header('X-unique-key', '');
            $userInfo->fill($data)->save();

            $volunteer = new Volunteer();
            $volunteer->phone = $userInfo->phone;
            $volunteer->org_id = $userInfo->org_id;
            $volunteer->user_id = $userInfo->id;
            $volunteer->identifier = 'V'.date('ymd').sprintf('%06d', $userInfo->id);
            $volunteer->score = Org::getScoreConf()['register'];
            $orgId = $this->getOrdId();
            if($orgId == 38)
            {
                $volunteer->slogan = '志愿小金人，用爱传温暖！';
            }
            $volunteer->save();

            $format = $userInfo->getAllInfo();
            $format['token'] = $userInfo->token;

            DB::table('user_score_item')->insert(['user_id'=>$userInfo->id, 'type'=>0, 'score'=>Org::getScoreConf()['register'], 'remark'=>'注册奖励']);
            DB::commit();
            Log::info('SCORE 注册奖励积分 userId:'.$userInfo->id.'  score:'.Org::getScoreConf()['register']);
            $this->setData($format);
            return $this->response();

        }catch (\Exception $e)
        {
            Log::info(request()->all());
            Log::info($e->getMessage());
            DB::rollBack();
            $this->setStatus(-10001);
            $this->setMsg('服务器忙,请稍后重试');
            return $this->response();
        }

    }

    public function loginByPhone(Request $request)
    {
        $rules = [  'phone'=>'required|is_phone', 'verify_code'=>'required',];
        $validator = Validator::make(Input::all(), $rules);
        if($validator->fails())
        {
            $errors = $validator->errors();
            $this->setStatus(10001);
            $this->setMsg(implode(' ', $errors->all()));

            return $this->response();
        }

        if(empty(request()->header('X-unique-key', '')))
        {
            $this->setStatus(10001);
            $this->setMsg('unique key为必填');

            return $this->response();
        }


        $phone = $request->input('phone');
        $verifyCode = $request->input('verify_code');
        //检查验证码
        $checkSms = SmsCode::checkVerifyCode($phone, $verifyCode);
        if( !$checkSms )
        {
            $this->setStatus(10001);
            $this->setMsg('短信验证码错误,请重新获取验证码!');
            return $this->response();
        }

        $user = User::where('org_id', $this->getOrdId())->where('type', 1)->where('phone', $phone)->first();

        //新用户
        if(empty($user))
        {
            return $this->_registerByPhone();
        }

        $token = User::createToken();
        User::where('open_id', request()->header('X-unique-key', ''))->where('id', '!=', $user->id)->update(['open_id'=>'']);
        $user->fill(['token'=>$token, 'open_id'=>request()->header('X-unique-key', '')])->save();

        $format = $user->getAllInfo();
        $format['token'] = $user->token;

        $this->setData($format);
        return $this->response();

    }
    public function login(Request $request)
    {
        $rules = ['username' => 'required', 'pwd'=>'required'];
        $validator = Validator::make(Input::all(), $rules);
        if($validator->fails())
        {
            $errors = $validator->errors();
            $this->setStatus(10001);
            $this->setMsg(implode(' ', $errors->all()));

            return $this->response();
        }

        if(empty(request()->header('X-unique-key', '')))
        {
            $this->setStatus(10001);
            $this->setMsg('unique key为必填');

            return $this->response();
        }


        $username = $request->input('username');
        $pwd = $request->input('pwd');
        $type = 1;
        $volunteer = Volunteer::where('org_id', $this->getOrdId())->where('id_number', $username)->first();
        if(empty($volunteer))
        {
            $user = User::where(function($query) use ($username){
                $query->where('username', $username)->orwhere('phone', $username);
            })->where('type', $type)->where('org_id', $this->getOrdId())->first();
        }else{
            $user = User::where(function($query) use ($username, $volunteer){
                $query->where('username', $username)->orwhere('phone', $username)->orwhere('id', $volunteer->user_id);
            })->where('type', $type)->where('org_id', $this->getOrdId())->first();
        }


        //密码错误
        if(empty($user) || !Hash::check($pwd, $user->pwd))
        {
            $this->setStatus(10001);
            $this->setMsg('用户名或密码错误');
            return $this->response();
        }
        User::where('open_id', request()->header('X-unique-key', ''))->where('id', '!=', $user->id)->update(['open_id'=>'']);

        $token = User::createToken();
        $user->fill(['token'=>$token, 'open_id'=>request()->header('X-unique-key', '')])->save();

        $format = $user->getAllInfo();
        $format['token'] = $user->token;

        $this->setData($format);
        return $this->response();
    }

    public function info(Request $request)
    {
        $userInfo = User::where('type', 1)->where('token', $this->getToken())->first();

        $format = $userInfo->getAllInfo();
        $format['join_project_count'] = UserProject::where('user_id', $userInfo->id)->where('verify_status', 1)->where('reward_time', '>', 0)->count();

        $format['token'] = $userInfo->token;

        $this->setData($format);
        return $this->response();
    }

    public function edit(Request $request)
    {
        $rules = ['avatars'=>'url', 'slogan'=>'string',  'email'=>'string', 'good_at'=>'array|max:3', ];
        $validator = Validator::make(Input::all(), $rules);
        if($validator->fails())
        {
            $errors = $validator->errors();
            $this->setStatus(10001);
            $this->setMsg(implode(' ', $errors->all()));

            return $this->response();
        }

        $userInfo = User::where('type', 1)->where('token', $this->getToken())->first();

        $volunteer = Volunteer::where('user_id', $userInfo->id)->first();

        if(!empty($request->input('avatars')))
        {
            $userInfo->avatars = $request->input('avatars');
            $userInfo->save();
        }


        if(!empty($request->input('email')))
        {
            $userInfo->email = $request->input('email');
            $userInfo->save();
        }


        if(!empty($request->input('slogan')))
        {
            $volunteer->slogan = $request->input('slogan');
            $volunteer->save();
        }
        $goodAt = $request->input('good_at');
        if(!empty($goodAt))
        {
            VolunteerGoodAt::where('user_id', $userInfo->id)->delete();

            $goodConf = Conf::get('good_at');
            foreach($goodAt as $item)
            {

                if(!in_array($item, $goodConf))
                {
                    continue;
                }
                $vgood = new VolunteerGoodAt();
                $vgood->org_id = $userInfo->org_id;
                $vgood->user_id = $userInfo->id;
                $vgood->good_at_name = $item;
                $vgood->save();
            }
        }
        $data = $userInfo->getAllInfo();
        $this->setData($data);

        return $this->response();
    }

    public function realname(Request $request)
    {
        $orgInfo = Org::where('id', $this->getOrdId())->first();


        $rules = [
            'avatars'=> $orgInfo->real_name_register == 1 && $orgInfo->custom_config['open_avatars'] == 1? 'required|url': '',
            'real_name' => $orgInfo->real_name_register == 1 && $orgInfo->custom_config['open_real_name'] == 1? 'required': '',
            'id_number'=> $orgInfo->real_name_register == 1 && $orgInfo->custom_config['open_id_number'] == 1? 'required': '',
            'nation'=> $orgInfo->real_name_register == 1 && $orgInfo->custom_config['open_nation'] == 1? 'required': '',
            'province_id'=> $orgInfo->real_name_register == 1 && $orgInfo->custom_config['open_addr'] == 1? 'required|exists:area,id': '',
            'city_id'=> $orgInfo->real_name_register == 1 && $orgInfo->custom_config['open_addr'] == 1? 'required|exists:area,id': '',
            'county_id'=> $orgInfo->real_name_register == 1 && $orgInfo->custom_config['open_addr'] == 1? 'required|exists:area,id': '',
            'addr'=> $orgInfo->real_name_register == 1 && $orgInfo->custom_config['open_addr'] == 1? 'required': '',
            'extends'=>'array'
        ];


        $validator = Validator::make(Input::all(), $rules);
        if($validator->fails())
        {
            $errors = $validator->errors();
            $this->setStatus(10001);
            $this->setMsg(implode(' ', $errors->all()));

            return $this->response();
        }
        $input = Input::all();

        if(($orgInfo->real_name_register == 1 && $orgInfo->custom_config['open_real_name']) && !preg_match('/^[\x{4e00}-\x{9fa5}]+$/u', $request->input('real_name')))
        {
            $this->setStatus(10001);
            $this->setMsg('姓名只能由汉字组成');
            return $this->response();
        }
        $idNumber = $request->input('id_number');
        $idCard = new IdCard();

        $userInfo = User::where('type', 1)->where('token', $this->getToken())->first();

        if( ($orgInfo->real_name_register == 1 && $orgInfo->custom_config['open_id_number'] == 1)   )
        {
            if(($idCard->isChinaIdCard($idNumber)) == false)
            {
                $this->setStatus(10001);
                $this->setMsg('实名制认证失败,请填写合法的身份证信息.');
                return $this->response();
            }

            $haveUser = Volunteer::where('org_id', $this->getOrdId())->where('user_id', '!=', $userInfo->id)->where('id_number', $idNumber)->count();
            if($haveUser != 0)
            {
                $this->setStatus(10001);
                $this->setMsg('身份证已被其他用户使用');
                return $this->response();
            }
        }



        if($request->get('avatars'))
        {
            $userInfo->avatars = $request->get('avatars');
            $userInfo->save();
        }

        $volunteer = Volunteer::where('user_id', $userInfo->id)->first();
        if(!empty($volunteer->id_number))
        {
            $this->setStatus(10002);
            $this->setMsg('您已完成过实名认证,请勿重复认证!');
            return $this->response();
        }

        foreach ($orgInfo->custom_config['extends'] as $value)
        {
            if($value['is_required'] == 1 &&   empty($input['extends'][$value['key']]) )
            {
                $this->setStatus(10001);
                $this->setMsg($value['label'].'为必填项目');
                return $this->response();
            }
        }
        $data = Input::all();
        if(!empty($idNumber))
        {
            $data['birthday'] = substr($idNumber, 6, 4).'-'.substr($idNumber, 10, 2).'-'.substr($idNumber, 12, 2);
        }

        $data['sex'] = ((int)substr($idNumber,16,1)) % 2 === 1? 1:2;
        $area = Area::getList([$data['province_id'], $data['city_id'], $data['county_id']]);
        $data['province_name'] = $area[$data['province_id']]['name'];
        $data['city_name'] = $area[$data['city_id']]['name'];
        $data['county_name'] = $area[$data['county_id']]['name'];

        $volunteer->fill($data)->save();
        $volunteer->increment('score', Org::getScoreConf()['certification']);
        Log::info('SCORE 实名认证奖励积分 userId:'.$userInfo->id.'  score:'.Org::getScoreConf()['certification']);
        DB::table('user_score_item')->insert(['user_id'=>$userInfo->id, 'type'=>0, 'score'=>Org::getScoreConf()['certification'], 'remark'=>'实名认证奖励']);
        $data = $userInfo->getAllInfo();
        $this->setData($data);
        return $this->response();
    }

    public function resetPwd(Request $request)
    {
        $rules = ['phone'=>'required|is_phone', 'verify_code'=>'required', 'pwd'=>'required'];
        $validator = Validator::make(Input::all(), $rules);
        if($validator->fails())
        {
            $errors = $validator->errors();
            $this->setStatus(10001);
            $this->setMsg(implode(' ', $errors->all()));

            return $this->response();
        }

        if(!preg_match('/^[a-zA-Z0-9]+$/u', $request->input('pwd')) || strlen($request->input('pwd')) < 6 || strlen($request->input('pwd')) > 20)
        {
            $this->setStatus(10001);
            $this->setMsg('密码只能由数字或者字母组成,长度在6~20字符');
            return $this->response();
        }

        $phone = $request->input('phone');
        $verifyCode = $request->input('verify_code');
        //检查验证码
        $checkSms = SmsCode::checkVerifyCode($phone, $verifyCode);
        if( !$checkSms )
        {
            $this->setStatus(10001);
            $this->setMsg('短信验证码错误,请重新获取验证码!');
            return $this->response();
        }

        $userInfo = User::where('type', 1)->where('token', $this->getToken())->first();

        //已登录,必须用自己的手机号修改密码
        if(!empty($userInfo) && $userInfo->phone != $phone  )
        {
            $this->setStatus(10001);
            $this->setMsg('非法请求!');
            return $this->response();

        }else{

            $userInfo = User::where('type', 1)->where('phone', $phone)->where('org_id', $this->getOrdId())->first();
        }

        if(empty($userInfo))
        {
            $this->setStatus(10001);
            $this->setMsg('手机号错误，该手机号暂未注册!');
            return $this->response();
        }
        $userInfo->pwd = Hash::make($request->input('pwd'));
        $userInfo->save();

        $data = $userInfo->getAllInfo();

        $this->setData($data);
        return $this->response();
    }

    public function resetPhone(Request $request)
    {
        $rules = ['phone'=>'required|is_phone', 'verify_code'=>'required',];

        $validator = Validator::make(Input::all(), $rules);
        if($validator->fails())
        {
            $errors = $validator->errors();
            $this->setStatus(10001);
            $this->setMsg(implode(' ', $errors->all()));

            return $this->response();
        }

        $phone = $request->input('phone');
        $verifyCode = $request->input('verify_code');
        //检查验证码
        $checkSms = SmsCode::checkVerifyCode($phone, $verifyCode);
        if( !$checkSms )
        {
            $this->setStatus(10001);
            $this->setMsg('短信验证码错误,请重新获取验证码!');
            return $this->response();
        }

        $has = User::where('type', 1)->where('phone', $phone)->where('org_id', $this->getOrdId())->where('token', '!=', $this->getToken())->count();

        if($has != 0)
        {
            $this->setStatus(10001);
            $this->setMsg('该手机号已被其他用户使用!');
            return $this->response();
        }

        $userInfo = User::where('type', 1)->where('token', $this->getToken())->first();



        $userInfo->phone = $phone;

        $userInfo->save();

        $data = $userInfo->getAllInfo();

        $this->setData($data);
        return $this->response();
    }
    public function collection(Request $request)
    {
        $rules = ['type'=>'required|in:0,1', 'id'=>'required|integer', ];
        $validator = Validator::make(Input::all(), $rules);
        if($validator->fails())
        {
            $errors = $validator->errors();
            $this->setStatus(10001);
            $this->setMsg(implode(' ', $errors->all()));

            return $this->response();
        }

        $userInfo = User::where('type', 1)->where('token', $this->getToken())->first();

        $type = $request->input('type');
        $id = $request->input('id');

        switch($type)
        {
            case 0:
                $relation = Project::where('org_id', $this->getOrdId())->where('id', $id)->where('status',1)->where('verify_status', 1)->first();
                break;

            case 1:
                $relation = Team::where('org_id', $this->getOrdId())->where('id', $id)->where('verify_status', 1)->first();
                break;

            default:
                $request = null;
                break;
        }

        if(empty($relation))
        {
            $this->setStatus(10001);
            $this->setMsg('收藏出错,未知的id');

            return $this->response();
        }

        $userCollection = UserCollection::where('user_id', $userInfo->id)->where('type', $type)->where('relation_id', $id)->first();

        if(!empty($userCollection))
        {
            $this->setStatus(10001);
            $this->setMsg('您已成功收藏!');

            return $this->response();
        }else
        {
            $userCollection = new UserCollection();
        }

        $data = Input::all();
        $data['type'] = $type;
        $data['relation_id'] = $id;
        $data['user_id'] = $userInfo->id;

        $userCollection->fill($data)->save();

        return $this->response();
    }

    public function deleteCollection(Request $request)
    {
        $rules = ['type'=>'required|in:0,1', 'id'=>'required|integer', ];
        $validator = Validator::make(Input::all(), $rules);
        if($validator->fails())
        {
            $errors = $validator->errors();
            $this->setStatus(10001);
            $this->setMsg(implode(' ', $errors->all()));

            return $this->response();
        }

        $userInfo = User::where('type', 1)->where('token', $this->getToken())->first();

        $type = $request->input('type');
        $id = $request->input('id');

        switch($type)
        {
            case 0:
                $relation = Project::where('org_id', $this->getOrdId())->where('id', $id)->where('status',1)->where('verify_status', 1)->first();
                break;

            case 1:
                $relation = Team::where('org_id', $this->getOrdId())->where('id', $id)->where('verify_status', 1)->first();
                break;

            default:
                $request = null;
                break;
        }

        if(empty($relation))
        {
            $this->setStatus(10001);
            $this->setMsg('收藏出错,未知的id');

            return $this->response();
        }

        UserCollection::where('user_id', $userInfo->id)->where('type', $type)->where('relation_id', $id)->delete();

        return $this->response();
    }

    public function collectList(Request $request)
    {
        $rules = ['type'=>'required|in:0,1'];
        $validator = Validator::make(Input::all(), $rules);
        if($validator->fails())
        {
            $errors = $validator->errors();
            $this->setStatus(10001);
            $this->setMsg(implode(' ', $errors->all()));

            return $this->response();
        }
        $userInfo = User::where('type', 1)->where('token', $this->getToken())->first();
        $type = $request->input('type');
        switch($type)
        {
            case 0:
                $nodes = UserCollection::with('project');
                break;

            case 1:
                $nodes = UserCollection::with('team');
                break;
        }
        $nodes = $nodes->where('type', $type)->where('user_id', $userInfo->id);
        $nodes = $nodes->orderBy('id', 'desc');
        $nodes = $nodes->get();

        $list = [];
        foreach($nodes as $node)
        {
            switch($type)
            {
                case 0:
                    $tmp = Project::format($node->project);
                    $tmp['team'] = Team::format($node->project->team);
                    break;

                case 1:
                    $tmp = Team::format($node->team);
                    break;
            }
            $list[] = $tmp;
        }

        $data['list'] = $list;

        $this->setData($data);
        return $this->response();
    }

    public function logout(Request $request)
    {
        $userInfo = User::where('type', 1)->where('token', $this->getToken())->first();

        DB::update('update user set token = null , open_id=null where id = ?', [$userInfo->id]);

        return $this->response();
    }

    public function scoreList(Request $request, $type)
    {
        $pageNum = request()->input('current_page', 1);
        $pageSize = request()->input('page_size', 10);
        $from = ($pageNum - 1)*$pageSize;

        $userInfo = User::where('type', 1)->where('token', $this->getToken())->first();

        $nodes = UserScore::where('type', $type)->where('user_id', $userInfo->id);

        $count = $nodes->count();
        $nodes = $nodes->orderBy('id','desc');

        $lists = $nodes->take($pageSize)->skip($from)->get();

        $pageInfo = [
            "current_page" => intval($pageNum),
            "total_page" => ceil($count / $pageSize),
            "page_size" => intval($pageSize)
        ];

        $list = [];
        foreach($lists as $value)
        {
            $list[] = UserScore::format($value);
        }

        $data['list'] = $list;
        $data['page'] = $pageInfo;
        $this->setData($data);

        return $this->response();
    }
}
